﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using ZaxLib.Web.UI.Events;
using ZaxLib.Web.Writers.Nodes;

namespace ZaxLib.Web.UI.WebControls
{
	[DefaultProperty("Text")]
	[ToolboxData("<{0}:DragPanel runat=server></{0}:DragPanel>")]
	public class DropPanel : ZaxControl
	{
		#region Data Structures

		class ListItem
		{
			public String Text;
			public String CssClass;

			public ListItem(String inText)
			{
				Text = inText;
				CssClass = String.Empty;
			}

			public ListItem(String inText, String css)
			{
				Text = inText;
				CssClass = css;
			}
		}

		#endregion

		#region Parameters

		private ArrayList _items = null;
		[Browsable(false)]
		public ArrayList Items
		{
			get
			{
				if (_items == null)
				{
					_items = new ArrayList();
					if (HasText(Text))
					{
						String[] aItems = Text.Split(',');
						foreach (String item in aItems)
						{
							AddItem(item);
						}
					}
				}

				return _items;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String HoverClass
		{
			get
			{
				String s = ViewState["HoverClass"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["HoverClass"] = value;
			}
		}

		[Bindable(true)]
		[Category("Panel Settings")]
		[DefaultValue("")]
		[Localizable(true)]
		public String AllowItems
		{
			get
			{
				String s = ViewState["AllowItems"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["AllowItems"] = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String RemoveClass
		{
			get
			{
				String s = ViewState["RemoveClass"] as String;
				return (s == null ? "placeholder" : s);
			}
			set
			{
				ViewState["RemoveClass"] = value;
			}
		}

		[Bindable(true)]
		[Category("Panel Settings")]
		[DefaultValue("")]
		[Localizable(true)]
		public String PlaceHolder
		{
			get
			{
				String s = ViewState["PlaceHolder"] as String;
				return (s == null ? "Place Items Here" : s);
			}
			set
			{
				ViewState["PlaceHolder"] = value;
			}
		}

		[Bindable(true)]
		[Category("Panel Settings")]
		[DefaultValue("")]
		[Localizable(true)]
		public String PanelManagerName
		{
			get
			{
				String s = String.Format("{0}_panelManager", ID);
				if (ViewState["PanelManagerName"] != null)
				{
					s = ViewState["PanelManagerName"].ToString();
				}

				return s;
			}
			set
			{
				ViewState["PanelManagerName"] = value;
			}
		}

		#endregion

		#region Control Writers

		protected override void ControlWrite(HtmlTextWriter writer)
		{
			base.ControlWrite(writer);
			// Write list
			ListWrite(writer);
			// Write input to manage drops
			InputWrite(writer);

			// Write jQuery code for dropping items on this element
			INode top = CodeWriter.CreateTopNode();
			INode node = CodeWriter.CreateReadyFunction(top);
			CodeWriter.AddChild(ID, node).SelectorId();
			INode droppable = CodeWriter.AddChild("droppable").Joined();
			node = CodeWriter.AddParam("").ObjectDef();
			if (HoverClass.Trim().Length > 0)
			{
				CodeWriter.AddParam("hoverClass", String.Format("\"{0}\"", HoverClass), node).VarDef();
			}
			if (AllowItems.Trim().Length > 0)
			{
				CodeWriter.AddParam("accept", String.Format("\".{0}\"", AllowItems), node).VarDef();
			}

			INode param = CodeWriter.AddParam("drop", node).VarDef();
			INode func = CodeWriter.AddChild("function", param).Function();
			CodeWriter.AddParam("event", func).VarDef();
			CodeWriter.AddParam("ui", func).VarDef();


			CodeWriter.AddChild("ui.draggable.remove();", func).RawCode();

			if (IsDropped)
			{
				CodeWriter.AddChild("\tvar index = ui.draggable.text();", func).RawCode();
				//CodeWriter.AddChild(String.Format("\t$(\"input[name={0}]\").value = index;", PanelManagerName), func).RawCode();
				CodeWriter.AddChild(String.Format("\t__doPostBack(\"{0}\", \"{1}[\" + index + \"]\");", UniqueID, DROPPED)).RawCode();
				if(IsClicked)
				{
					INode click = CodeWriter.AddChild("click", droppable).Joined();
					func = CodeWriter.AddParam("function", click).Function();
					CodeWriter.AddParam("event", func).VarDef();
					CodeWriter.AddParam("ui", func).VarDef();
					CodeWriter.AddChild("\tvar index = event.originalEvent.originalTarget.innerHTML;", func).RawCode();
					//CodeWriter.AddChild(String.Format("\t$(\"input[name={0}]\").value = index;", PanelManagerName), func).RawCode();
					CodeWriter.AddChild(String.Format("\t__doPostBack(\"{0}\", \"{1}[\" + index + \"]\");", UniqueID, CLICKED), func).RawCode();
				}
			}
			else
			{
				CodeWriter.AddChild("this", func).Selector();
				node = CodeWriter.AddChild("find").Joined();
				CodeWriter.AddParam(String.Format("\".{0}\"", RemoveClass)).VarDef();
				CodeWriter.AddChild("remove", node).Joined();
				CodeWriter.AddParam("").VarDef();

				CodeWriter.AddChild("\"<li></li>\"", func).Selector();
				node = CodeWriter.AddChild("text").Joined();
				CodeWriter.AddParam("ui.draggable.text()").VarDef();
				CodeWriter.AddChild("appendTo").Joined();
				CodeWriter.AddParam("this").VarDef();
			}
		}

		protected void ListWrite(HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Id, ID);
			if (CssClass.Trim().Length > 0)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
			}
			writer.RenderBeginTag(HtmlTextWriterTag.Ul);
			if (Items.Count == 0)
			{
				AddItem(PlaceHolder, RemoveClass);
			}

			foreach (ListItem item in Items)
			{
				writer.Flush();
				if (item.CssClass != String.Empty)
				{
					writer.AddAttribute(HtmlTextWriterAttribute.Class, item.CssClass);
				}
				writer.RenderBeginTag(HtmlTextWriterTag.Li);
				writer.Write(item.Text);
				writer.RenderEndTag();
				writer.WriteLine();
			}
			writer.RenderEndTag();
			writer.Flush();
		}

		protected void InputWrite(HtmlTextWriter writer)
		{
			writer.Flush();
			writer.AddAttribute(HtmlTextWriterAttribute.Id, UniqueID);
			writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
			writer.AddAttribute(HtmlTextWriterAttribute.Name, PanelManagerName);
			writer.AddAttribute(HtmlTextWriterAttribute.Value, Text);
			writer.RenderBeginTag(HtmlTextWriterTag.Input);
			writer.RenderEndTag();
			writer.Flush();

		}

		#endregion

		#region Render Methods

		protected override void RenderContents(HtmlTextWriter writer)
		{
			// Transfer items in the list to the text parameter for storage
			if(Items.Count > 0)
			{
				String[] list = new String[Items.Count];
				for(int i=0; i<Items.Count; i++)
				{
					list[i] = (Items[i] as ListItem).Text;
				}
				Text = String.Join(",", list);
			}
			base.RenderContents(writer);
		}

		#endregion

		#region Data Methods

		public void AddItem(String item)
		{
			AddItem(item, String.Empty);
		}

		public void AddItem(String item, String css)
		{
			ListItem lItem = new ListItem(item, css);
			if(_items == null)
			{
				int parse = Items.Count;
			}
			_items.Add(lItem);
		}

		public void Clear()
		{
			if (_items != null)
			{
				_items.Clear();
			}
		}

		#endregion

		#region Data Handlers

		public override void RaisePostBackEvent(String Command, String Arg)
		{
			base.RaisePostBackEvent(Command, Arg);
			// Handle the event
			switch (Command.ToUpper())
			{
				case CLICKED:
					{
						ControlEventArgs ce = new ControlEventArgs(Arg);
						OnClick(ce);
					}

					break;
				case DROPPED:
					{
						DropEventArgs de = new DropEventArgs(Arg);
						OnDrop(de);
					}
					break;
			}

		}// End method RaisePostBackEvent

		#endregion

		#region Events

		public event EventHandler Drop;

		public bool IsDropped
		{
			get
			{
				return Drop != null;
			}
		}

		public void OnDrop(DropEventArgs e)
		{
			if (IsDropped)
			{
				Drop(this, e);
			}
		}// End method OnDrop

		public event EventHandler Click;
		[Browsable(false)]
		public bool IsClicked
		{
			get
			{
				return Click != null;
			}
		}

		public virtual void OnClick(EventArgs e)
		{
			if (IsClicked)
			{
				Click(this, e);
			}
		}

		#endregion
	}
}
